﻿using DatabaseProxy.Attributes;
using System.Reflection;

namespace DatabaseProxy.ObjectSql
{
    public class ObjectSqlManager<T> where T: IDatabaseTable
    {
        private static string _querySql = "";
        public static string QuerySql
        { 
            get 
            {
                Type type = typeof(T);
                string tableName = type.Name;
                if (type.IsDefined(typeof(TableNameAttribute), false))
                {
                    TableNameAttribute? tableNameAttribute = type.GetCustomAttribute<TableNameAttribute>();
                    tableName = tableNameAttribute?.Name ?? tableName;
                }
                if (!string.IsNullOrEmpty(_querySql))
                {
                    return _querySql;
                }
                else
                {
                    var properties = type.GetProperties();
                    _querySql = $"SELECT {string.Join(',', properties.Select(l =>
                    {
                        string columnName = l.Name;
                        if (l.IsDefined(typeof(ColumnNameAttribute), false))
                        {
                            ColumnNameAttribute? columnNameAttribute = l.GetCustomAttribute<ColumnNameAttribute>();
                            columnName = columnNameAttribute?.Name ?? columnName;
                        }
                        return columnName;
                    }).ToList())} FROM {tableName}";
                    return _querySql;
                }
            }
        }

        private static string _queryByPrimaryKeySql = "";
        public static string QueryByPrimaryKeySql
        {
            get
            {
                Type type = typeof(T);
                if (!string.IsNullOrEmpty(_queryByPrimaryKeySql))
                {
                    return _queryByPrimaryKeySql;
                }
                else
                {
                    var properties = type.GetProperties();
                    string tableName = type.Name;
                    if (type.IsDefined(typeof(TableNameAttribute), false))
                    {
                        TableNameAttribute? tableNameAttribute = type.GetCustomAttribute<TableNameAttribute>();
                        tableName = tableNameAttribute?.Name ?? tableName;
                    }
                    var columnNames = properties.Select(l =>
                    {
                        string columnName = l.Name;
                        if (l.IsDefined(typeof(ColumnNameAttribute), false))
                        {
                            ColumnNameAttribute? columnNameAttribute = l.GetCustomAttribute<ColumnNameAttribute>();
                            columnName = columnNameAttribute?.Name ?? columnName;
                        }
                        return columnName;
                    });
                    _queryByPrimaryKeySql = $"SELECT {string.Join(',', columnNames)} FROM {tableName} WHERE Id=@id";
                    return _queryByPrimaryKeySql;
                }
            }
        }
    }

    public class ObjectSqlManagerDic
    {
        private static Dictionary<string, string> QuerySqlDictionary;
        private static Dictionary<string, string> QuerySqlByPrimaryKeyDictionary;

        static ObjectSqlManagerDic()
        {
            QuerySqlDictionary = new();
            QuerySqlByPrimaryKeyDictionary = new();
        }

        public static string GetQuerySql<T>()
        {
            Type type = typeof(T);
            if (QuerySqlDictionary.ContainsKey(type.Name))
            {
                return QuerySqlDictionary[type.Name];
            }
            else
            {
                var properties = type.GetProperties();
                string sql = $"SELECT {string.Join(',', properties.Select(l => l.Name).ToList())} FROM {type.Name}";
                QuerySqlDictionary.Add(type.Name, sql);
                return sql;
            }
        }

        public static string GetQueryByPrimaryKeySql<T>()
        {
            var type = typeof(T);
            if (QuerySqlByPrimaryKeyDictionary.ContainsKey(type.Name))
            { 
                return QuerySqlByPrimaryKeyDictionary[type.Name];
            }
            else
            {
                var properties = type.GetProperties();
                string sql = $"SELECT {string.Join(',', properties.Select(l => l.Name).ToList())} FROM {type.Name} WHERE Id=@id";
                QuerySqlByPrimaryKeyDictionary.Add(type.Name, sql);
                return sql;
            }
        }
    }
}
